use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{info, warn, error};
use crate::response::AppError;

/// 事务操作
pub type TransactionOp = Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = Result<(), AppError>> + Send>> + Send>;

/// 补偿操作
pub type CompensationOp = Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = Result<(), AppError>> + Send>> + Send>;

/// 事务步骤
pub struct TransactionStep {
    /// 步骤名称
    pub name: String,
    /// 事务操作
    pub operation: TransactionOp,
    /// 补偿操作（用于回滚）
    pub compensation: Option<CompensationOp>,
}

/// 分布式事务管理器（简化版，用于本地事务协调）
pub struct TransactionManager {
    /// 已执行的步骤（用于回滚）
    executed_steps: Arc<Mutex<Vec<(String, Option<CompensationOp>)>>>,
}

impl TransactionManager {
    /// 创建新的事务管理器
    pub fn new() -> Self {
        Self {
            executed_steps: Arc::new(Mutex::new(Vec::new())),
        }
    }

    /// 执行事务
    pub async fn execute_transaction(&self, steps: Vec<TransactionStep>) -> Result<(), AppError> {
        let mut executed_steps = self.executed_steps.lock().await;
        
        for step in steps {
            info!("执行事务步骤: {}", step.name);
            
            // 执行操作
            match (step.operation)().await {
                Ok(()) => {
                    info!("事务步骤 {} 执行成功", step.name);
                    // 保存补偿操作用于可能的回滚
                    executed_steps.push((step.name.clone(), step.compensation));
                }
                Err(e) => {
                    error!("事务步骤 {} 执行失败: {}", step.name, e);
                    
                    // 执行回滚
                    self.rollback_internal(&mut executed_steps).await;
                    
                    return Err(AppError::business(&format!(
                        "事务在步骤 '{}' 失败，已执行回滚: {}",
                        step.name, e
                    )));
                }
            }
        }

        info!("所有事务步骤执行成功");
        Ok(())
    }

    /// 手动回滚事务
    pub async fn rollback(&self) -> Result<(), AppError> {
        let mut executed_steps = self.executed_steps.lock().await;
        self.rollback_internal(&mut executed_steps).await
    }

    /// 内部回滚实现
    async fn rollback_internal(
        &self,
        executed_steps: &mut Vec<(String, Option<CompensationOp>)>,
    ) -> Result<(), AppError> {
        info!("开始事务回滚，需要回滚 {} 个步骤", executed_steps.len());

        let mut rollback_errors = Vec::new();

        // 按相反顺序执行补偿操作
        while let Some((step_name, compensation)) = executed_steps.pop() {
            if let Some(compensation_op) = compensation {
                info!("回滚步骤: {}", step_name);
                match compensation_op().await {
                    Ok(()) => {
                        info!("步骤 {} 回滚成功", step_name);
                    }
                    Err(e) => {
                        error!("步骤 {} 回滚失败: {}", step_name, e);
                        rollback_errors.push(format!("步骤 '{}': {}", step_name, e));
                    }
                }
            } else {
                warn!("步骤 {} 没有补偿操作，跳过回滚", step_name);
            }
        }

        if rollback_errors.is_empty() {
            info!("事务回滚完成");
            Ok(())
        } else {
            error!("事务回滚部分失败: {:?}", rollback_errors);
            Err(AppError::internal(&format!(
                "事务回滚部分失败: {}",
                rollback_errors.join(", ")
            )))
        }
    }
}

impl Default for TransactionManager {
    fn default() -> Self {
        Self::new()
    }
}

/// 便捷宏：创建事务步骤
#[macro_export]
macro_rules! transaction_step {
    ($name:expr, $op:expr) => {
        $crate::transaction::TransactionStep {
            name: $name.to_string(),
            operation: Box::new(|| Box::pin($op)),
            compensation: None,
        }
    };
    ($name:expr, $op:expr, $comp:expr) => {
        $crate::transaction::TransactionStep {
            name: $name.to_string(),
            operation: Box::new(|| Box::pin($op)),
            compensation: Some(Box::new(|| Box::pin($comp))),
        }
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    use tokio::time::{sleep, Duration};

    #[tokio::test]
    async fn test_successful_transaction() {
        let tm = TransactionManager::new();
        
        let steps = vec![
            transaction_step!("步骤1", async { 
                sleep(Duration::from_millis(10)).await;
                Ok(()) 
            }),
            transaction_step!("步骤2", async { 
                sleep(Duration::from_millis(10)).await;
                Ok(()) 
            }),
        ];

        let result = tm.execute_transaction(steps).await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_failed_transaction_with_rollback() {
        let tm = TransactionManager::new();
        
        let steps = vec![
            transaction_step!(
                "步骤1", 
                async { Ok(()) },
                async { 
                    println!("回滚步骤1");
                    Ok(()) 
                }
            ),
            transaction_step!("步骤2", async { 
                Err(AppError::business("模拟失败"))
            }),
        ];

        let result = tm.execute_transaction(steps).await;
        assert!(result.is_err());
    }
} 